﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Chainsaw.Interfaces;

namespace ErepIrcBot
{
    public class Plugin : IPlugin
    {

        private readonly ExecuteCommandEventArgs _eventArgs = new ExecuteCommandEventArgs();

        private Dictionary<string, List<string>> listyNickow = new Dictionary<string, List<string>>();

        private Dictionary<int, Bitwa> bitwy = new Dictionary<int, Bitwa>();

        private Dictionary<int, int> killeWBitwach = new Dictionary<int, int>();
        
        private Dictionary<int, int> stronaResistance = new Dictionary<int, int>();

        private HashSet<int> allIny = new HashSet<int>();

        private List<Komenda> komendy = new List<Komenda>();

        private Bitwa aktualnaBitwa;

        private Slap slap;

        private Status status;

        private static System.Object lockNick = new System.Object();

        public Bitwa AktualnaBitwa
        {
            get { return aktualnaBitwa; }
            set { aktualnaBitwa = value; }
        }

        private Statystyki statystyki = new Statystyki();

        internal Statystyki Statystyki
        {
            get { return statystyki; }
            set { statystyki = value; }
        }


        public event EventHandler<ExecuteCommandEventArgs> ExecuteCommand;

        private string egov;

        public string Egov
        {
            get { return egov; }
            set { egov = value; }
        }

        private bool zbiorka;

        public bool Zbiorka
        {
            get { return zbiorka; }
            set { zbiorka = value; }
        }

        public bool jestBitwa(int numer)
        {
            return bitwy.ContainsKey(numer);
        }

        public void dodajBitwe(Bitwa bitwa)
        {
            if (!bitwy.ContainsKey(bitwa.Numer))
                bitwy.Add(bitwa.Numer, bitwa);
        }

        public Bitwa dajBitwe(int numer)
        {
            return bitwy[numer];
        }

        public List<Bitwa> wszystkieBitwy()
        {
            List<Bitwa> wynik = new List<Bitwa>();
            foreach (KeyValuePair<int, Bitwa> b in bitwy)
            {
                wynik.Add(b.Value);
            }
            return wynik;
        }

        public void skasujBitwy()
        {
            bitwy.Clear();
        }

        public void slapuj(string channel)
        {
            slap.slapuj(channel);
        }

        #region IPlugin Members

        public void Dispose()
        {
            foreach (Komenda k in komendy)
                k.usunKomende();
        }


        public void Load()
        {
            slap = new Slap(this);
            status = new Status(this);
            komendy.Add(slap);
            komendy.Add(status);
          //  komendy.Add(new Zbiorka(this));
            komendy.Add(new KomendaBitwaZwykla(this));
            komendy.Add(new KomendaBitwaResistance(this));
            komendy.Add(new KomendaBitwaAll(this));
            komendy.Add(new KomendaBitwaHold(this));
            komendy.Add(new Kille(this));
            komendy.Add(new Koniec(this));
            komendy.Add(new Egov(this));
            komendy.Add(new Tanki(this));
            komendy.Add(new Rozdajacy(this));
            komendy.Add(new KomendaStatystyki(this));
            komendy.Add(new Dof(this));

            foreach (Komenda k in komendy)
                k.zarejestrujKomende();
        }

        public void OnInternalMessage(string text)
        {
            
        }

        public void OnNickAdd(string channel, string nick, string host, string server)
        {
            if (!String.IsNullOrEmpty(channel) && !String.IsNullOrEmpty(nick))
            {
                addPerson(channel, nick);
                if (zbiorka)
                    status.wypiszStatus(nick);
            }
        }

        public void OnNickChange(string oldNick, string newNick, string server)
        {
            if (!String.IsNullOrEmpty(oldNick) && !String.IsNullOrEmpty(newNick))
            {
                nickChanged(oldNick, newNick);
            }
        }

        public void OnNickRemove(string channel, string nick, string reason, string server)
        {
            if (!String.IsNullOrEmpty(channel) && !String.IsNullOrEmpty(nick))
            {
                removePerson(channel, nick);
            }
        }

        public void OnPrivateMessage(string nick, string text, string channel, int userLevel, string server)
        {

            foreach (Komenda k in komendy)
                k.wykonajKomende(text, channel, userLevel, nick);
        }

        public void OnRawMessage(string data, string server)
        {
            
        }

        #endregion

        public void przeslijDoBota(string komenda)
        {
            _eventArgs.Command = komenda;
            ExecuteCommand(this, _eventArgs);
        }

        public string dajImiona(string channel)
        {
            string imiona = "";
            foreach (string imie in listyNickow[channel])
                imiona += imie + " ";
            return imiona;
        }

        private bool poprawnyKanalNick(string channel, string nick)
        {
            return !String.IsNullOrEmpty(channel) && !String.IsNullOrEmpty(nick);
        }

        private void addPerson(string channel, string nick)
        {
            lock (lockNick)
            {
                if (poprawnyKanalNick(channel, nick))
                {
                    if (!listyNickow.ContainsKey(channel))
                    {
                        listyNickow.Add(channel, new List<string>());
                    }
                    listyNickow[channel].Add(nick);
                }
            }
        }

        private void removePerson(string channel, string nick)
        {
            lock (lockNick)
            {
                if (poprawnyKanalNick(channel, nick))
                    listyNickow[channel].Remove(nick);
            }
            
        }

        private void nickChanged(string oldNick, string newNick)
        {
            lock (lockNick)
            {
                if (poprawnyKanalNick(oldNick, newNick))
                {
                    foreach (KeyValuePair<string, List<string>> nickList in listyNickow)
                    {
                        if (nickList.Value.Contains(oldNick))
                        {
                            removePerson(nickList.Key, oldNick);
                            addPerson(nickList.Key, newNick);
                        }
                    }
                }
            }
            
            
        }

        

    }
}
